package com.mongodb.core;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter;

import com.google.gson.Gson;

/**
 * 模仿Mongodb实现数据库增删改查
 * @author feng
 * @createTime 2017年7月8日 20:48
 *
 */
public abstract class MongoDbTemplate {
	
	
	protected static final String _uuid = "_uuid";
	
	protected static final String PATH = "mini-mongodb.xml";
	
	/**
	 * 加载获取表的数据
	 * @param path
	 * @param tablename
	 * @return
	 * @throws Exception
	 */
	public final List<Map<String,Object>> loadTableDatas(final String path, final String tablename) throws Exception{
		Gson gson = new Gson();
		List<Map<String,Object>> ltdatas = new ArrayList<>();
		List<Element> list = this.childrenList(path);
		for (Element element : list) {
			if(element.getAttributeValue("name").equals(tablename)){
				List<Element> al = element.getChildren();
				for (Element s : al) {
					String text = s.getText();
					if (text == null) {
						break;
					}
					Map<String,Object> data = gson.fromJson(text, Map.class); //将JSON转成Map
					ltdatas.add(data);
				}
			}
		}
		return ltdatas;
	}
	
	public final List<Map<String,Object>> loadTableDatas(final String tablename) throws Exception{
		return this.loadTableDatas(PATH, tablename);
	}
	
	/**
	 * 添加数据
	 * @param path
	 * @param tablename
	 * @param obj
	 * @return
	 * @throws JDOMException
	 * @throws IOException
	 */
	public final boolean addData(final String path, final String tablename,final Object obj) throws JDOMException, IOException{
		Gson gson = new Gson();
		Document document = this.document(path);
		boolean flag = false;
		List<Element> list = this.childrenList(path,document);
		for (Element element : list) {
			if(tablesExits(element.getAttributeValue("name"), tablename)){
				Map<String,Object> baseMap = new HashMap<>();
				baseMap.put(_uuid, UUID.randomUUID().toString()); //使用UUID设置
				String json = gson.toJson(obj); //将对象设置成JSON
				Map<String,Object> objMap = gson.fromJson(json, Map.class); //将JSON转
				baseMap.putAll(objMap);
				Element dataElement = new Element("data");
				dataElement.addContent(gson.toJson(baseMap)); //将数据添加到data元素里
				element.addContent(dataElement); //将data 元素添加到table元素里
			}
		}
		XMLOutputter out = new XMLOutputter();
		out.output(document, new FileOutputStream(path));
		flag = true;
		System.out
				.println("----------insert --- data --- success----------------------");
		return flag;
	}
	
	public final boolean addData(final String tablename,final Object obj) throws JDOMException, IOException{
		return addData(PATH, tablename, obj);
	}
	
	/**
	 * 更新数据
	 * @param path
	 * @param tablename
	 * @param obj
	 * @return
	 * @throws JDOMException
	 * @throws IOException
	 */
	public boolean updateData(final String path, final String tablename, final Object obj) throws JDOMException, IOException{
		Gson gson = new Gson();
		boolean flag = false;
		Document document = this.document(path);
		List<Element> list = this.childrenList(path,document);
		for (Element element : list) {
			if(tablesExits(element.getAttributeValue("name"), tablename)){
				List<Element> al = element.getChildren();
				for (Element s : al) {
					// 如果定位Data[通过UUID唯一标示]
					Map<String,Object> jsonMap = gson.fromJson(s.getText(), Map.class);
					Map<String,Object> newmp = gson.fromJson(gson.toJson(obj), Map.class);
					if (jsonMap.get(_uuid).equals(newmp.get(_uuid))) {
						jsonMap.putAll(newmp);
						Element data = new Element("data");
						data.setText(gson.toJson(jsonMap));
						element.removeContent(s);
						element.addContent(data);
						break;
					}
				}
			}
		}
		XMLOutputter out = new XMLOutputter();
		out.output(document, new FileOutputStream(path));
		flag = true;
		System.out
		.println("----------update --- data --- success----------------------");
		return flag;
	}
	
	public boolean updateData(final String tablename, final Object obj) throws JDOMException, IOException{
		return updateData(PATH, tablename, obj);
	}
	
	/**
	 * 删除数据
	 * @param path
	 * @param tablename
	 * @param po
	 * @return
	 * @throws JDOMException
	 * @throws IOException
	 */
	public final boolean deleteData(final String path, final String tablename, final Object po)
			throws JDOMException, IOException {
		Gson gson = new Gson();
		boolean flag = false;
		Document document = this.document(path);
		List<Element> list = this.childrenList(path,document);
		for (Element x : list) {
			List<Element> al = x.getChildren();
			if (tablesExits(x.getAttributeValue("name"), tablename)) {
				for (Element s : al) {
					// 如果定位Data[通过UUID唯一标示]
					Map mp = gson.fromJson(s.getText(), Map.class);
					Map newmp = gson.fromJson(gson.toJson(po), Map.class);
					if (mp.get(_uuid).equals(newmp.get(_uuid))) {
						x.removeContent(s);
						break;
					}
				}
			}
		}
		XMLOutputter out = new XMLOutputter();
		out.output(document, new FileOutputStream(path));
		flag = true;
		System.out
		.println("----------delete --- data --- success----------------------");
		return flag;
	}
	
	public final boolean deleteData(final String tablename, final Object po) throws JDOMException, IOException{
		return deleteData(PATH, tablename, po);
	}
	
	/**
	 * 创建数据库
	 * @param path
	 * @param tableNames
	 * @return
	 * @throws Exception
	 */
	public final boolean createDataBase(final String path,final String ...tableNames) throws Exception {
		boolean flag = false;
		FileOutputStream file = new FileOutputStream(path);
		Document document = new Document();
		Element root = new Element("database");
		if(tableNames != null && tableNames.length > 0){
			for (String name : tableNames) {
				Element tableElement = new Element("table");
				tableElement.setAttribute("name", name);
				root.addContent(tableElement);
			}
		}
		document.setRootElement(root);
		XMLOutputter out = new XMLOutputter();
		out.output(document, file);
		flag = true;
		System.out
				.println("----------create---database---success-------------------");
		return flag;
	}
	
	public final boolean createDataBase(final String ...tableNames) throws Exception {
		return createDataBase(PATH, tableNames);
	}
	
	
	public final Document document(final String path) throws JDOMException, IOException{
		InputStream is = new FileInputStream(path);
		SAXBuilder saxBuilder = new SAXBuilder();
		Document document = saxBuilder.build(is);
		return document;
	}
	
	public final Element getRootElement(final String path,final Document document) throws JDOMException, IOException{
		Element root = document == null ? document(path).getRootElement()
										: document.getRootElement();
		return root;
	}
	
	public final Element getRootElement(final String path) throws JDOMException, IOException{
		return this.getRootElement(path, null);
	}
	
	public final List<Element> childrenList(final String path,final Document document) throws JDOMException, IOException{
		return this.getRootElement(path,document).getChildren();
	}
	
	public final List<Element> childrenList(final String path) throws JDOMException, IOException{
		return childrenList(path,null);
	}
	
	public final boolean tablesExits(final String name,final String tablename){
		return name.equals(tablename);
	}
	

}
